#coding: utf-8

from move import Move


class SquareFactory(type):
    u'''产生方块的工厂 '''

    def __init__(cls, name, bases, dic):
        super(SquareFactory, cls).__init__(name, bases, dic)
        cls.instances = {}

    def __call__(cls, x, y):
        #cls.xs和cls.ys表示该种方块合法的x和合法的y
        if x not in cls.xs or y not in cls.ys:
            return None
        _ = x, y
        if _ not in cls.instances:
            cls.instances[_] = super(SquareFactory, cls).__call__(x, y)
        return cls.instances[_]


class Square(object):
    u'''左上角坐标为(0, 0)，右下角坐标为(3, 4)'''

    __metaclass__ = SquareFactory

    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.position = self.x + 4 * self.y
        self.mask = 0
        for x, y in self.ps:
            x = self.x + x
            y = self.y + y
            self.mask |= 1 << (x + 4 * y)
        self._moves = None

    @property
    def moves(self):
        if self._moves is None:
            self._moves = []
            for x, y in [(0, 1), (0, -1), (1, 0), (-1, 0)]:
                dst = self.__class__(self.x + x, self.y + y)
                if dst:
                    self._moves.append(Move(self, dst))
        return self._moves

    @property
    def positions(self):
        for x, y in self.ps:
            x = self.x + x
            y = self.y + y
            yield x, y

    def __lt__(self, other):
        u''' 对象的坐标比较 '''
        return self.hash < other.hash

    def __str__(self):
        u''' 对象的输出 '''
        return '%s at (%d, %d)' % (self.__class__.__name__, self.x, self.y)
    __repr__ = __str__


class Box(Square):
    u''' 2×2方块'''
    C = 'B'
    id = 0
    count = 4
    xs = range(3)
    ys = range(4)
    ps = [(0, 0), (1, 0), (0, 1), (1, 1)]

    @property
    def hash(self):
        return self.position << 60


class Dot(Square):
    u'''1×1方块'''
    C = 'D'
    id = 3
    count = 1
    xs = range(4)
    ys = range(5)
    ps = ((0, 0), )

    @property
    def hash(self):
        return 1 << self.position


class VerticalBar(Square):
    u'''1×2方块'''
    C = 'V'
    id = 2
    count = 2
    xs = range(4)
    ys = range(4)
    ps = (0, 0), (0, 1)

    @property
    def hash(self):
        return 1 << (self.position+40)


class HorizontalBar(Square):
    u'''2×1方块'''
    C = 'H'
    id = 1
    count = 2
    xs = range(3)
    ys = range(5)
    ps = (0, 0), (1, 0)

    @property
    def hash(self):
        return 1 << (self.position+20)
